package com.blue.gateway.paycore.wxpay;

import lombok.extern.slf4j.Slf4j;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContexts;

import javax.net.ssl.SSLContext;
import java.io.File;
import java.io.FileInputStream;
import java.security.KeyStore;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@Slf4j
public final class SSLConSocketFactory {

    private static volatile Map<String, SSLConnectionSocketFactory> sslFactory = new ConcurrentHashMap<>();

    private SSLConSocketFactory() {

    }

    private static SSLConnectionSocketFactory buildSSLConSocketFactory(String certPath, String keyPassword) {
        KeyStore keyStore;
        try (FileInputStream inStream = new FileInputStream(new File(certPath));) {
            keyStore = KeyStore.getInstance("PKCS12");
            keyStore.load(inStream, keyPassword.toCharArray());
            SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, keyPassword.toCharArray()).build();
            return new SSLConnectionSocketFactory(sslcontext, new String[]{"TLSv1"}, null, SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
        } catch (Exception e) {
            log.error("", e);
        }
        return null;
    }

    public static SSLConnectionSocketFactory get(String certPath, String keyPassword) {
        if (!sslFactory.containsKey(certPath)) {
            synchronized (SSLConSocketFactory.class) {
                if (!sslFactory.containsKey(certPath)) {
                    SSLConnectionSocketFactory sslConnectionSocketFactory = buildSSLConSocketFactory(certPath, keyPassword);
                    if (sslConnectionSocketFactory != null) {
                        sslFactory.put(certPath, sslConnectionSocketFactory);
                    } else {
                        log.error("buildSSLConSocketFactory error. certPath:{}", certPath);
                        return null;
                    }
                }
            }
        }
        return sslFactory.get(certPath);
    }
}
